#include "sobjc/runtime.h"
#include "sobjc/class.h"
#include "sobjc/selector.h"
#include "sobjc/classes/Object.h"
#include "sobjc/classes/ConstantString.h"

@implementation Object

+ (void)initialize
{
}

+ (Instance)new
{
  return [[self alloc] init];
}

+ (Instance)alloc
{
  return objc_class_make_instance(self);
}

- (Self)init
{
  return self;
}

- (void)free
{
  objc_free(self);
}

- (Self)copy
{
  return self;
}

+ (Class)class
{
  return objc_class_get_metaclass(self);
}

+ (Class)superclass
{
  return objc_class_get_superclass(self);
}

+ (const char *)name
{
  return objc_class_get_name(self);
}

- (Class)class
{
  return isa;
}

- (Class)superclass
{
  return isa->superclass;
}

- (const char *)name
{
  return isa->name;
}

- (Self)self
{
  return self;
}

- (unsigned int)hash
{
  return (unsigned int)self;
}

- (BOOL)isEqual:(id)anObject
{
  return [anObject hash];
}

- (BOOL)isKindOfClass:(Class)aClass
{
  return objc_class_is_kind_of(isa, aClass);
}

- (BOOL)isMemberOfClass:(Class)aClass
{
  return isa == aClass;
}

+ (BOOL)instancesRespondToSelector:(SEL)aSelector
{
  return objc_class_get_instance_method(self, aSelector) != NULL;
}

- (BOOL)respondsToSelector:(SEL)aSelector
{
  return [isa instancesRespondToSelector: aSelector];
}

- (BOOL)conformsToProtocol:(Protocol *)aProtocol
{
  /* FIXME */
  return NO;
}

+ (BOOL)conformsToProtocol:(Protocol *)aProtocol
{
  /* FIXME */
  return NO;
}

- (IMP)methodForSelector:(SEL)aSelector
{
  return [isa instanceMethodForSelector: aSelector];
}

+ (IMP)instanceMethodForSelector:(SEL)aSelector
{
  return objc_class_get_imp(self, aSelector);
}

- (id)performSelector:(SEL)aSelector
{
  return (*objc_class_get_imp(isa, aSelector))(self, aSelector);
}

- (id)performSelector:(SEL)aSelector withObject:(id)anObject
{
  return (*objc_class_get_imp(isa, aSelector))(self, aSelector, anObject);
}

- (id)performSelector:(SEL)aSelector
           withObject:(id)anObject
           withObject:(id)anotherObject
{
  return (*objc_class_get_imp(isa, aSelector))
      (self, aSelector, anObject, anotherObject);
}

- (void)subclassResponsibilitySelector:(SEL)aSelector
{
  printf("error: subclass must implement '%s'\n",
         objc_sel_get_name(aSelector));
}

- (void)notImplementedSelector:(SEL)aSelector
{
  printf("error: '%s' is not implemented\n", objc_sel_get_name(aSelector));
}

- (void)doesNotRecognizeSelector:(SEL)aSelector
{
  printf("error: '%s' does not recognize '%s'\n", [self name],
         objc_sel_get_name(aSelector));
}

@end

